/***************************************************************************
 *   Copyright (C) 2008 by Ryszard Krol   *
 *   rysiek.krol@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "imagereader.h"
#include "picturemanager.h"
#include "updateiconevent.h"
#include "picturelistwidgetitem.h"
#include "updatestatusbarevent.h"
#include "rexifdata.h"

#include <QDir>
#include <QFileInfoList>
#include <QFileInfo>
#include <QListWidgetItem>
#include <QApplication>
#include <QFile>
#include <QList>
#include <QListIterator>
#include <zlib.h>





/**
* Konstruktor
 */
ImageReader::ImageReader ( PictureManager *manager, QDir *dir )
                : QThread()
{
        this->manager = manager;
        this->dir = dir;
        this->isActive = true;
        sendIconGenerationCompleateEvent = false;
        this->start ( QThread::LowPriority );
}

/**
* Destruktor
*/
ImageReader::~ImageReader()
{
        delete dir;
}

void ImageReader::run()
{
        while (true) {
                mutex.lock();
                this->isActive = true;
                mutex.unlock();
                this->generateItems();
                this->setIsActive(false);
                if (this->manager->getListWidget()->count()>0) {
                        this->waitMutex.lock();
                        this->readDirCondition.wait(&this->waitMutex);
                        this->waitMutex.unlock();
                }
        }
}

/**
* Generates item from files in directory
*/
void ImageReader::generateItems()
{
        qRegisterMetaType<QModelIndex> ( "QModelIndex" );
        QFileInfoList fileInfoList = this->dir->entryInfoList (QDir::Dirs, QDir::Name );

        for ( int i = 0; i<fileInfoList.size() ;i++ ) {
                if (!this->isActive) {
                        this->sendIconGenerationCompleateEvent = true;
                        break;
                }
                QFileInfo fileInfo = fileInfoList.at ( i );
                new PictureListWidgetItem (
                        fileInfo,this->manager->getListWidget() );
        }
        QApplication::postEvent ( manager, new QEvent ( QEvent::Type ( ViewerEvent::ListRefreshNeeded ) ) );

        //Dodawanie plikow do listy
        QStringList filters;
        filters << "*.jpg" << "*.png" << "*.bmp"<<"*.jpeg"<<"*.JPG"<<"*.JPEG";
        fileInfoList = this->dir->entryInfoList ( filters,QDir::Files,QDir::Name );
        //lista wskaznikow do sortowania
        QList<PictureListWidgetItem*> *lista = new QList<PictureListWidgetItem*>();

        //Wypelnianie listy wskaznikow
        for ( int i = 0; i<fileInfoList.size();i++ ) {
                if (!this->isActive) {
                        this->sendIconGenerationCompleateEvent = true;
                        break;
                }
                QFileInfo fileInfo = fileInfoList.at ( i );
                lista->append(new PictureListWidgetItem (fileInfo));
        }
        if (lista->count()>0)QApplication::postEvent ( manager, new UpdateStatusBarEvent( QString::number(lista->count()) + " items"));

        //sortowanie listy
        this->sortItems(lista, 0, lista->count() -1);

        //wypelnianie QListWidgetu posortowanymi elementami

        QListIterator<PictureListWidgetItem*> listaIterator(*lista);
        while (listaIterator.hasNext()) {
                if (!this->isActive) {
                        this->sendIconGenerationCompleateEvent = true;
                        break;
                }
                this->manager->getListWidget()->addItem(listaIterator.next());
        }
        //Sygnal do zrefreshowania listy
        QApplication::postEvent ( manager, new QEvent ( QEvent::Type ( ViewerEvent::ListRefreshNeeded )));
        for ( int i = 0; i<this->manager->getListWidget()->count();i++ ) {

                if (!this->isActive) {
                        this->sendIconGenerationCompleateEvent = true;
                        break;
                }
                PictureListWidgetItem *item = dynamic_cast<PictureListWidgetItem*> ( this->manager->getListWidget()->item ( i ) );
                QFileInfo file = item->getFile();
                UpdateIconEvent *event = new UpdateIconEvent (this->generateIcon ( item->getFile() ),item );
                if (this->isActive)QApplication::postEvent ( manager, event );
        }
        delete lista;

        if (this->sendIconGenerationCompleateEvent == true) {
                this->sendIconGenerationCompleateEvent = false;
                if (this->isActive)QApplication::postEvent ( manager, new QEvent ( QEvent::Type ( ViewerEvent::iconGenerationCompleateEvent ) ));
        }

}

/**
* Sorts Widget List
*/
void ImageReader::sortItems ( QList<PictureListWidgetItem*> *lista, int beg, int end )
{
        if ( beg<end ) {
                int m=beg;
                for ( int i=beg+1;i<=end;i++ ) {
                        if ( this->compareItems(lista->at ( i ), lista->at ( beg )) ) lista->swap ( ++m,i );
                }
                lista->swap ( beg,m );
                this->sortItems ( lista,beg,m-1 );
                this->sortItems ( lista,m+1,end );
        }
}

/**
* Generates Icon
*/
QImage  ImageReader::generateIcon ( const QFileInfo  &filePatch )
{
        QImage result;
        if (filePatch.exists()) {
                if ( filePatch.isFile() ) {
                        RExifData *exifData = new RExifData(filePatch.absoluteFilePath().toLatin1().data());
                        if (exifData->isExif()) {
                                result = exifData->getThumbnail();
                        }
                        if (result.isNull()) {
                        	QString string = filePatch.absoluteFilePath();
                                result.load( filePatch.absoluteFilePath() );
                                result = result.scaled ( QSize ( 150,150 ),Qt::KeepAspectRatio );
                        }
                        delete exifData;
                }
        }
        return result;
}

/**
* Sets  ImageReader Thread  active variable
*/
void ImageReader::setIsActive ( bool theValue )
{
        mutex.lock();
        isActive = theValue;
        mutex.unlock();
}

/**
* Returns current Directory
*/
QDir* ImageReader::getDir() const
{
        return dir;
}

/**
* Sets current Directory
*/
void ImageReader::setDir ( QDir* theValue )
{
        mutex.lock();
        dir = theValue;
        mutex.unlock();
}

/**
* returns is ImageReader Thread active
*/
bool ImageReader::active()
{
        bool w;
        mutex.lock();
        w = this->isActive;
        mutex.unlock();
        return w;
}

/**
* Returns true, if items should be swaped by sort algorytm
*/
bool ImageReader::compareItems(PictureListWidgetItem * firstItem, PictureListWidgetItem * secondItem)
{
        switch (this->manager->getItsProperty()->getSortMethod()) {
        case Property::ByCommentDate:
                if ( (firstItem->isDate() && secondItem->isDate()) && ( firstItem->getDateTime() <secondItem->getDateTime() ) )
                        return true;
                break;
        case Property::ByFileName:
                if ( firstItem->getFile().fileName() <secondItem->getFile().fileName() ) return true;
        default:
                if ( (firstItem->isDate() && secondItem->isDate()) && ( firstItem->getDateTime() <secondItem->getDateTime() ) )
                        return true;
        }
        return false;
}
